#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h> 
#include <sys/stat.h>
#include <fcntl.h>

// 声明信号处理函数，用于处理接收到的信号
void sig_handler(int, siginfo_t*, void*);

int main(int argc, char** argv)
{
    // 定义 sigaction 结构体，用于设置信号处理的行为
    struct sigaction act;
    // 定义信号集，newmask 用于存储要屏蔽的信号，oldmask 用于保存当前的信号屏蔽集
    sigset_t newmask, oldmask;
    int rc; 

    // 清空信号集 newmask，确保其中不包含任何信号
    sigemptyset(&newmask); 
    // 将 SIGINT 信号添加到信号集 newmask 中，SIGINT 通常是用户按下 Ctrl+C 时产生的信号
    sigaddset(&newmask, SIGINT); 
    // 将 SIGRTMIN 信号添加到信号集 newmask 中，SIGRTMIN 是第一个实时信号
    sigaddset(&newmask, SIGRTMIN);   
    // 阻塞 newmask 中包含的信号，并将当前的信号屏蔽集保存到 oldmask 中
    sigprocmask(SIG_BLOCK, &newmask, &oldmask);   

    // 设置信号处理函数为 sig_handler
    act.sa_sigaction = sig_handler;
    // 设置信号处理标志为 SA_SIGINFO，表示使用 sa_sigaction 而不是 sa_handler 来处理信号
    act.sa_flags = SA_SIGINFO; 

    // 为 SIGINT 信号安装信号处理函数
    if (sigaction(SIGINT, &act, NULL) < 0)
    {
        // 如果安装失败，输出错误信息
        printf("install signal error\n");
    } 
    // 为 SIGRTMIN 信号安装信号处理函数
    if (sigaction(SIGRTMIN, &act, NULL) < 0)
    {
        // 如果安装失败，输出错误信息
        printf("install signal error\n");
    }

    // 输出当前进程的 PID，方便外部向该进程发送信号
    printf("pid = %d\n", getpid());

    // 让程序休眠 60 秒，在此期间程序可以接收并处理信号
    sleep(60); 

    // 恢复原来的信号屏蔽集，即解除对 newmask 中信号的阻塞
    sigprocmask(SIG_SETMASK, &oldmask, NULL); 

    return 0;
}

// 信号处理函数的具体实现
void sig_handler(int signum, siginfo_t *info, void *myact)
{
    // 判断接收到的信号是否为 SIGINT
    if (signum == SIGINT)
        // 如果是 SIGINT 信号，输出相应信息
        printf("Got a common signal\n");
    else
        // 如果是其他信号（这里主要是 SIGRTMIN），输出实时信号信息
        printf("Got a real time signal\n");
}